/**
 * MiniGolf Scorecard
 * Copyright (C) 2010  MiriTheQuiet, http://minigolfscorecard.googlecode.com/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package cz.mtq.mgsc.export.csv;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;

import cz.mtq.mgsc.model.Player;
import cz.mtq.mgsc.model.Players;

/**
 * 
 * @author MiriTheQuiet
 *
 */
public final class PlayersToCsvExport {

	/**
	 * This encoding must be supported with every >= midp 2.0 implementation
	 */
	public static final String ENCODING = "UTF-8";
	
	private static final char VALUE_DELIMITER = ',';
	
	private static final int HEADER_BUFFER_LENGHT;
	
	private static final String NEW_LINE_SEPARATOR = System.getProperty("line.separator") != null ? System.getProperty("line.separator") : "\n";
	
	static {
		//Player.NUMBER_OF_HOLES = , characters delimiting holes
		int v = Player.NUMBER_OF_HOLES;
		//1 = , character delimiting last hole and sum cell
		v +=  1;
		//Player.NUMBER_OF_HOLES + 9 = single and double digit holes
		for (int i = 1; i <= Player.NUMBER_OF_HOLES; i++){
			//magnitudes higher than tens are not supported
			v +=  i < 10 ? 1 : 2;
		}
		//new line character
		v += NEW_LINE_SEPARATOR.length();
		HEADER_BUFFER_LENGHT = v;
	}
	
	private PlayersToCsvExport(){}
	
	/**
	 *  
	 * @param players
	 * @param os which is not closed by this method
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	public static void export(Players players, OutputStream os) throws UnsupportedEncodingException, IOException {
		if (players != null && players.size() > 0){
			writeHeader(os);
			for (int i = 0; i < players.size(); i++){
				write(players.getPlayer(i), os);
			}
		}
	}
	
	/**
	 * @param os
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	private static void writeHeader(OutputStream os) throws UnsupportedEncodingException, IOException{
		StringBuffer sb = new StringBuffer(HEADER_BUFFER_LENGHT);
		for (int i = 1; i <= Player.NUMBER_OF_HOLES; i++){
			sb.append(VALUE_DELIMITER);
			sb.append(i);
		}
		sb.append(VALUE_DELIMITER);
		sb.append('\n');
		os.write(sb.toString().getBytes(ENCODING));
	}
	
	private static void write(Player p, OutputStream os) throws UnsupportedEncodingException, IOException{
		String sum = String.valueOf(p.getSum());
		//2 + p.getName().length() = name wrapped by " characters
	  //Player.NUMBER_OF_HOLES = , characters delimiting holes
  	//Player.NUMBER_OF_HOLES = player results on holes
	  //1 = , character delimiting last hole and sum cell
		//sum length
	  //1 = new line character
		StringBuffer sb = new StringBuffer(2 + p.getName().length() + Player.NUMBER_OF_HOLES + Player.NUMBER_OF_HOLES + 1 + sum.length() + 1);
		sb.append('\"');
		sb.append(p.getName());
		sb.append('\"');
		for (int i = 0; i < Player.NUMBER_OF_HOLES; i++){
			sb.append(VALUE_DELIMITER);
			sb.append(p.getHole(i));
		}
		sb.append(VALUE_DELIMITER);
		sb.append(sum);
		sb.append('\n');
		os.write(sb.toString().getBytes(ENCODING));
	}
	
	
	public static String createFileName(){
		StringBuffer sb = new StringBuffer(33);
		sb.append("mgsc-").append(toString(new Date())).append(".csv");
		return sb.toString();
	}
	
	private static char[] toString(Date date) {
		String toString = date.toString();
		//based on API doc
		String result = toString.substring(0, 19)+toString.substring(toString.length() - 5);
		char[] chars = result.toCharArray();
		if (chars != null) {
			for (int i = 0; i < chars.length; i++) {
				char c = chars[i];
				if (c == ' ' || c == ':') {
					chars[i] = '_';
				}
			}
		}
		return chars;
	}
}
